package pl.edu.mimuw.irs.core.model.analysis.resources;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import pl.edu.mimuw.irs.core.global.IDManager;
import pl.edu.mimuw.irs.core.model.analysis.TPair;
import pl.edu.mimuw.irs.core.model.analysis.dd.ActivityWrapper;
import pl.edu.mimuw.irs.core.model.petrinet.Transition;

public class Fire extends Transition {

	private static final long serialVersionUID = -2433639526909589702L;
	
	// *** Attributes

	private ActivityWrapper activity;
	private ResourcesGraph graph;
	private Map<ResourcePlace, TPair> hiringMap;
	public ActivityWrapper getActivity() {
		return activity;
	}
	public ResourcesGraph getGraph() {
		return graph;
	}
	public Map<ResourcePlace, TPair> getHiringMap() {
		if (hiringMap == null) hiringMap = 
			new LinkedHashMap<ResourcePlace, TPair>();
		return hiringMap;
	}
	
	// *** Constructors
	
	public Fire(IDManager idManager, ActivityWrapper activity, ResourcesGraph graph,
			Map<ResourcePlace, TPair> hiringMap) {
		super(idManager, idManager.getPrefixedNewId("Fire" + activity.getActivity().getId()), 
				activity.getActivity().getPosition().left().under());
		this.activity = activity;
		this.graph = graph;
		this.hiringMap = hiringMap;
	}
	
	// *** Methods
	
	private boolean invoke(boolean quiet) {
		/*
		 * Now we get some random of applicable resources and check if our
		 * choice covers the activity. If yes - we can hire them to proceed 
		 * with corresponding activity.
		 */
		Set<ResourcePlace> forFire = 
			new HashSet<ResourcePlace>(getActivity().getInvolvedResources().keySet());
		
		if (forFire == null) {
			return false;
		} else {
			fire(forFire);
			getActivity().setStarted(false);
			
			if (quiet) return true;
			else return super.invoke();
		}
	}
	
	@Override
	public boolean invoke() {
		return invoke(false);
	}
	
	/*
	 * Should be used only for rollback actions - it does not send nor consume
	 * tokens.
	 */
	public boolean quietInvoke() {
		return invoke(true);
	}
	
	private void fire(Set<ResourcePlace> forFire) {
		for (ResourcePlace resourcePlace : forFire) {
			resourcePlace.fire(activity);
		}
	}
}
